package com.five.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.five.api.AuthorServiceAPI;
import com.five.api.ReaderServiceAPI;
import com.five.dto.CommentCreateDTO;
import com.five.exception.BusinessException;
import com.five.jwt.JwtUtils;
import com.five.jwt.Payload;
import com.five.jwt.RsaUtils;
import com.five.mapper.CommentMapper;
import com.five.pojo.*;
import com.five.result.Result;
import com.five.service.ICommentService;
import com.five.vo.CommentTreeVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.URLDecoder;
import java.security.PublicKey;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements ICommentService {
    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    private ReaderServiceAPI readerServiceAPI;
    @Autowired
    private AuthorServiceAPI authorServiceAPI;
//    @Autowired
//    private NovelServiceAPI novelServiceAPI;

    /**
     * 创建评论/回复（支持无限层级）
     */
    @Override
    public Long createComment(String token, CommentCreateDTO dto) {
        LoginInfo logininfo = tokenToLoginInfo(token);

        // 2. 验证书籍存在（顶级评论直接校验，子回复追溯父级书籍ID）
        Long novelId = dto.getNovelId();
        if (dto.getParentId() != null) {
            // 子回复：通过父级评论获取书籍ID并校验父级存在
            Comment parent = commentMapper.selectById(dto.getParentId());
            // 修正：先判断 parent 不为 null，再判断 isDelete 不为 null 且为 1
            if (parent == null || (parent.getIsDeleted() != null && parent.getIsDeleted() == 1)) {
                throw new BusinessException("父级评论不存在或已删除");
            }
            novelId = parent.getNovelId(); // 子回复继承父级书籍ID
        } else {
            // 顶级评论：直接验证书籍存在
//            Novel novel=novelServiceAPI.queryNovelDetail(novelId);
//            if (novel==null) {
//                throw new BusinessException("书籍不存在");
//            }
        }

        // 3. 保存评论
        Comment comment = new Comment();
        comment.setNovelId(novelId);
        comment.setParentId(dto.getParentId());
        comment.setLogininfoId(logininfo.getId());
        comment.setType(logininfo.getType());
        comment.setContent(dto.getContent());
        comment.setCreateTime(new Date());
        comment.setIsDeleted(0);
        commentMapper.insert(comment);

        // 4. 返回结果
        return comment.getId();
    }

    /**
     * 查询所有评论（含所有层级子回复）
     */
    @Override
    public List<CommentTreeVO> getCommentTree(Long novelId) {
        // 1. 查询某本书的所有顶级评论（parent_id=null，未删除）
        List<Comment> topComments = commentMapper.selectTopComments(novelId);
        if (topComments.isEmpty()) {
            return Collections.emptyList();
        }
        // 2. 递归查询所有子回复（无限层级，不限制深度）
        return topComments.stream()
                .map(topComment -> buildTreeRecursive(topComment)) // 无层级限制，递归到底
                .collect(Collectors.toList());
    }

    /**
     * 递归构建评论树（无限层级）
     */
    private CommentTreeVO buildTreeRecursive(Comment comment) {
        Integer type = comment.getType();

        // 1. 基础信息转换
        CommentTreeVO vo = new CommentTreeVO();
        vo.setCommentId(comment.getId());
        vo.setParentId(comment.getParentId());
        vo.setNovelId(comment.getNovelId());
        vo.setLogininfoId(comment.getLogininfoId());
        vo.setType(type);
        vo.setContent(comment.getContent());
        vo.setCreateTime(comment.getCreateTime());

        // 2. 补充用户信息（昵称、头像）
        if(type==1){
            Result<Author> authorResult = authorServiceAPI.queryByLoginInfoId(comment.getLogininfoId());
            Author author = authorResult.getData();
            vo.setName(author.getPenName());
            vo.setAvatar(author.getAvatar());
        }else if(type==2){
            Result<Reader> readerResult = readerServiceAPI.queryByLoginInfoId(comment.getLogininfoId());
            Reader reader = readerResult.getData();
            vo.setName(reader.getNickname());
            vo.setAvatar(reader.getAvatar());
        }else {
            vo.setName("未知用户");
        }

        // 3. 递归查询所有子回复（无限层级）
        List<Comment> children = commentMapper.selectByParentId(comment.getId());
        if (!children.isEmpty()) {
            vo.setChildren(children.stream()
                    .map(this::buildTreeRecursive) // 继续递归子回复
                    .collect(Collectors.toList()));
        } else {
            vo.setChildren(Collections.emptyList());
        }
        return vo;
    }

    /**
     * 删除评论/回复（软删除）
     */
    @Override
    public void deleteComment(String token, Long commentId) {
        LoginInfo logininfo = tokenToLoginInfo(token);
        // 1. 校验评论存在
        Comment comment = commentMapper.selectById(commentId);
        if (comment == null || comment.getIsDeleted() == 1) {
            throw new BusinessException("评论不存在或已删除");
        }
        // 2. 权限校验：仅创建者可删除
        if (!comment.getLogininfoId().equals(logininfo.getId())) {
            throw new BusinessException("无权限：仅创建者可删除");
        }
        // 3. 软删除
        comment.setIsDeleted(1);
        commentMapper.updateById(comment);
    }

    /**
     * 查询登录人创建的评论/回复
     */
    @Override
    public List<Comment> listByLogininfo(String token) {
        LoginInfo logininfo = tokenToLoginInfo(token);
        return commentMapper.selectByLogininfoId(logininfo.getId());
    }

    /*
     * 根据token获取登录人信息
     * */
    public LoginInfo tokenToLoginInfo(String token) {
        PublicKey publicKey;
        LoginInfo logininfo;
        try {
            publicKey = RsaUtils.getPublicKey(URLDecoder.decode(
                    JwtUtils.class.getClassLoader().getResource("hrm_auth_rsa.pub").getFile(), "UTF-8"));
            Payload<Map> payload = JwtUtils.getInfoFromToken(token, publicKey, Map.class);
            // 4. 获取"loginInfo"对应的JSON对象，并转换为LoginInfo
            Object loginInfoObj = payload.getUserInfo().get("loginInfo");
            // 关键：使用FastJSON将JSON对象反序列化为LoginInfo（核心解决类型转换问题）
            logininfo = JSON.toJavaObject((JSONObject) loginInfoObj, LoginInfo.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return logininfo;
    }
}